﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Win32;

namespace SQLBackup
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            var args = App.gArgs;

            if (Utility.CheckNullState(args))
            {
                try
                {
                    var configFilePath = args[1].Split('-')[1];
                    new DbBackUp(configFilePath).RunDbBackUp();

                    if (args[0] == "-auto")
                    {
                        Process.GetCurrentProcess().Kill();
                    }
                }
                catch (Exception excpt)
                {
                    Utility.LogErrorToFile(excpt.ToString());
                }
            }
            else
            {
                InitializeComponent();
                BindDbListDbName();
                BindBackupType();
                var connectionString =  Config.DBConnectionString; 

                var arryCon = connectionString.Split(';');

                foreach (var str in arryCon.Where(str => str.ToUpper().StartsWith("DATA")))
                {
                    lblMessage.Content = str;
                }
            }
        }

        /// <summary>
        /// Button click to generate the xml file 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGenrateConfig_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!FormIsValid()) return;

                if (!txtConfigFileName.Text.EndsWith(".xml"))
                {
                    txtConfigFileName.Text += ".xml";
                }
                var objconfig = new ConfigSettings
                {
                    DbBackUpFilePath = txtBackUpPath.Text,
                    DbName = cmbDBName.SelectedItem.ToString(),
                    ActivityLogPath = Convert.ToString(lblActivity.Content),
                    BackupType = cmbBackupType.SelectedItem.ToString()//Convert.ToBoolean(chkIsDifferential.IsChecked)
                };

                if (!Directory.Exists(objconfig.DbBackUpFilePath))
                {
                    Directory.CreateDirectory(objconfig.DbBackUpFilePath);
                }
                if (!Directory.Exists(objconfig.ActivityLogPath))
                {
                    Directory.CreateDirectory(objconfig.ActivityLogPath);
                }
                Utility.WriteSettingInXml(objconfig, txtConfigFileName.Text);
                MessageBox.Show("Setting saved!");
            }
            catch (Exception excpt)
            {
                Utility.LogErrorToFile(excpt.ToString());
                MessageBox.Show(excpt.ToString());
            }
        }

        /// <summary>
        /// Check all the controls in the forms and input is valid or not
        /// </summary>
        /// <returns></returns>
        private bool FormIsValid()
        {
            if (string.IsNullOrEmpty(Convert.ToString(cmbDBName.SelectedItem)))
            {
                lblMessage.Content = "Please select DataBase Name ";
                lblMessage.Foreground = Brushes.DarkRed;
                cmbDBName.Focus();
                return false;
            }

            if (string.IsNullOrEmpty(txtBackUpPath.Text))
            {
                lblMessage.Content = @"Please add backup file path like D:\SQLServer\Backups\ ";
                lblMessage.Foreground = Brushes.DarkRed;
                txtBackUpPath.Focus();
                return false;
            }

            if (string.IsNullOrEmpty(txtConfigFileName.Text))
            {
                lblMessage.Content = "Please Add config File Name Settings.xml";
                lblMessage.Foreground = Brushes.DarkRed;
                txtConfigFileName.Focus();
                return false;
            }
            return true;
        }

        /// <summary>
        /// upload an XML file 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUpload_click(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog {AddExtension = true, Filter = "XML Files (*.xml)|*.xml;"};
            
            var result = openFileDialog.ShowDialog();

            if (result != null && !result.Value) return;
            try
            {
                var configSettings = Utility.ReadSettingsFromXml(openFileDialog.FileName);

                txtBackUpPath.Text = configSettings.DbBackUpFilePath;
                txtConfigFileName.Text = openFileDialog.SafeFileName;
                cmbBackupType.SelectedValue = configSettings.BackupType;
                cmbDBName.SelectedValue = configSettings.DbName;
            }
            catch (Exception excpt)
            {
                Utility.LogErrorToFile(excpt.ToString());
                MessageBox.Show(excpt.ToString());
            }
        }

        private void btnCopyToClipboard_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(txtCopyToClip.Text))
            {
                Clipboard.SetText(txtCopyToClip.Text);
            }
            else
            {
                MessageBox.Show("Please click on Generate Argument button first");
            }
        }

        private void btnGeneratArgument_Click(object sender, RoutedEventArgs e)
        {
            GenerateSchedulerArgument();
        }

        /// <summary>
        /// Method to generate scheduler argument to be used in windows task scheduler as parameter
        /// to schedule a backup 
        /// </summary>
        private void GenerateSchedulerArgument()
        {
            var exePath = Assembly.GetEntryAssembly().Location;
            var exeDirectory = Path.GetDirectoryName(exePath);

            if (!txtConfigFileName.Text.EndsWith(".xml"))
            {
                txtConfigFileName.Text += ".xml";
            }

            var configFilePath = Path.Combine(exeDirectory, txtConfigFileName.Text);

            txtCopyToClip.Text = exePath + " -auto " + "path-" + configFilePath;
        }

        /// <summary>
        /// This method will fetch the list of all the DB name 
        /// Will bind those DB to the combo box
        /// </summary>
        private void BindDbListDbName()
        {
            const string sqlSelectClinic = @"SELECT NAME FROM SYS.DATABASES
                                         WHERE NAME NOT IN ('master', 'tempdb', 'model', 'msdb') ORDER BY NAME";

            try
            {
                using (var drDrpItems = ExecuteDataReader(sqlSelectClinic))
                {
                    while (drDrpItems.Read())
                    {
                       cmbDBName.Items.Add(drDrpItems["NAME"]);
                    }
                }
            }
            catch (Exception excpt)
            {
                Utility.LogErrorToFile(excpt.ToString());
                MessageBox.Show(excpt.ToString());
            }
        }

        private void BindBackupType()
        {
            try
            {
                cmbBackupType.Items.Add(Constant.K_FULL_BACKUP_TYPE);
                cmbBackupType.Items.Add(Constant.K_DIFFERENTIAL_BACKUP_TYPE);
            }
            catch (Exception excpt)
            {
                Utility.LogErrorToFile(excpt.ToString());
            }
        }

        /// <summary>
        /// This method is used to return the DbDataReader after executing random sql statements
        /// </summary>
        /// <param name="randomSql">Random SQL</param>
        /// <returns></returns>
        private static SqlDataReader ExecuteDataReader(string randomSql)
        {
            var storeConnection = new SqlConnection(Config.DBConnectionString);
            var command = storeConnection.CreateCommand();
            try
            {
                command.CommandText = randomSql;
                command.CommandTimeout = 1000;
                storeConnection.Open();

                var dataReader = command.ExecuteReader(CommandBehavior.CloseConnection);;

                return dataReader;
            }
            catch (SqlException)
            {
                storeConnection.Close();
                throw;
            }
        }

        private void btnShowSample_click(object sender, RoutedEventArgs e)
        {
            txtBackUpPath.Text= @"D:\SQLServer\Backups\";
            txtConfigFileName.Text = "FullConfig.xml";
            if (cmbDBName.Items.Count > 0)
            {
                cmbDBName.SelectedIndex = 0;
            }
            GenerateSchedulerArgument();
        }

        private void txtBackUpPath_TextChanged(object sender, TextChangedEventArgs e)
        {
            try
            {
                if (!txtBackUpPath.Text.Equals(string.Empty))
                {
                    var path = txtBackUpPath.Text;
                    var activityLogpath = Path.GetPathRoot(path);
                    var pathPart = path.Split(Path.DirectorySeparatorChar);

                    for (var partCount = 0; partCount < pathPart.Length - 1; partCount++)
                    {
                        if ((!partCount.Equals(0)))
                        {
                            activityLogpath = Path.Combine(activityLogpath, pathPart[partCount]);
                        }
                    }

                    lblActivity.Content = Path.Combine(activityLogpath, "ActivityLog");
                    //Path.Combine(Path.GetPathRoot(txtBackUpPath.Text), pathPart[])
                }
            }
            catch (Exception)
            {

            }
        }
    }
}
